//==========================================================================//
//                                                                          //
//  DHT22 Library               Version 0.1                     March 2012  //
//                                                                          //
//  Written for the Arduino Duemilanove w/ ATmega328                        //
//                                                                          //
//  DHT22 Arduino Library                                              //
//                                                                          //
//  Created by JFLagarde (jeanfrancoislagarde@hotmail.com)                  //
//                                                                          //
//  This file is part of OpenWS (http://code.google.com/p/openws/)          //
//                                                                          //
//==========================================================================//
//                                                                          //
//  Notes:                                                                  //
//                                                                          //
//                                                                          //
//==========================================================================//
//                                                                          //
//  Copyright 2012 Jean-Francois Lagarde (jeanfrancoislagarde@hotmail.com)  //
//  This program is distributed under the terms of                          //
//  the GNU General Public License                                          //
//                                                                          //
//  This program is free software: you can redistribute it and/or modify    //
//  it under the terms of the GNU General Public License as published by    //
//  the Free Software Foundation, either version 3 of the License, or       //
//  (at your option) any later version.                                     //
//                                                                          //
//  This program is distributed in the hope that it will be useful,         //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
//  GNU General Public License for more details.                            //
//                                                                          //
//  You should have received a copy of the GNU General Public License       //
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                          //
//==========================================================================//

#include <DHT22.h>

#define TIMEOUT 10000


// PUBLIC
DHT22::DHT22() {
	_lastHumidity = 0;
	_lastTemperature = 0;
}
void DHT22::init() {
	init(5);
}
void DHT22::init(byte pin) {
	_pin = pin;
}

// return values:
//  0 : OK
// -1 : checksum error
// -2 : timeout
int DHT22::read() {
	// READ VALUES
	int rv = readData();
	if (rv != 0) return rv;

	// CONVERT AND STORE
	_lastHumidity    = word(_bits[0], _bits[1]);

	int sign = 1;
	if (_bits[2] & 0x80) // negative temperature
	{
		_bits[2] = _bits[2] & 0x7F;
		sign = -1;
	}
	_lastTemperature = sign * word(_bits[2], _bits[3]);
	
	return testChecksum();
}
int DHT22::getTemperature() {
	return _lastTemperature;
}
int DHT22::getHumidity() {
	return _lastHumidity;
}





// PRIVATE

// return values:
//  0 : OK
// -2 : timeout
int DHT22::readData() {
	// INIT BUFFERVAR TO RECEIVE DATA
	uint8_t cnt = 7;
	uint8_t idx = 0;

	// EMPTY BUFFER
	for (int i=0; i< 5; i++) _bits[i] = 0;

	// REQUEST SAMPLE
	pinMode(_pin, OUTPUT);
	digitalWrite(_pin, LOW);
	delay(20);
	digitalWrite(_pin, HIGH);
	delayMicroseconds(40);
	pinMode(_pin, INPUT);

	// GET ACKNOWLEDGE or TIMEOUT
	unsigned int loopCnt = TIMEOUT;
	while(digitalRead(_pin) == LOW)
		if (loopCnt-- == 0) return -2;

	loopCnt = TIMEOUT;
	while(digitalRead(_pin) == HIGH)
		if (loopCnt-- == 0) return -2;

	// READ THE OUTPUT - 40 BITS => 5 BYTES
	for (int i=0; i<40; i++)
	{
		loopCnt = TIMEOUT;
		while(digitalRead(_pin) == LOW)
			if (loopCnt-- == 0) return -2;

		unsigned long t = micros();

		loopCnt = TIMEOUT;
		while(digitalRead(_pin) == HIGH)
			if (loopCnt-- == 0) return -2;

		if ((micros() - t) > 40) _bits[idx] |= (1 << cnt);
		if (cnt == 0)   // next byte?
		{
			cnt = 7;   
			idx++;      
		}
		else cnt--;
	}

	return 0;
}

int DHT22::testChecksum() {
	// TEST CHECKSUM
	uint8_t sum = _bits[0] + _bits[1] + _bits[2] + _bits[3];
	if (_bits[4] != sum) return -1;
	return 0;
}